#######################################################
# Example of a coupled DEVS model using two toaster DEVS models
# Author: moonho.hwang@gmail.com
#   Date: Oct.19.2011
#######################################################

from XSY.Set.Interval import *
from XSY.DEVS.Simulatable import *
from XSY.DEVS.CoupledDEVS import *
from XSY.DEVS.SimEngine import SimEngine

class Toaster(DEVS):
   '''an atomic DEVS for a toaster with uniform pdf toasting time'''
   def __init__(self, n, toasting_time, parent=None):
      '''constructor'''
      DEVS.__init__(self, n, parent)
      self.initphase = 'I'
      self.phase = self.initphase
      self.addInputPorts("?push")
      self.addOutputPorts("!pop")
      self.toast_time = toasting_time

   def delta_0(self):
      '''initialize function'''
      self.phase = self.initphase
      if self.phase == 'T': self.sigma = self.toast_time 
      else:                 self.sigma = float('inf')
          
   def ta(self):
      '''time advanced function'''
      return self.sigma

   def delta_ext(self, x):
      '''external transition function'''
      if self.phase == 'I' and x.port == self.IP["?push"]: 
         self.phase = 'T'
         self.sigma = self.toast_time
      else:
         self.sigma = self.timeRemaining() # recompute the remaining time
         
   def _lambda(self):
      '''output function'''
      if self.phase == 'T':
         return PortValue(self.OP["!pop"], None)

   def delta_int(self):
      '''internal transition function'''
      if self.phase == 'T':
         self.phase = 'I'
         self.sigma = float('inf')

   def state_to_s(self):
      '''convert state to string'''
      return str(self.phase)+','+"%.3f"%self.sigma
      

def make_input_event(md, JSONarg=None):
   '''a callback function for injection'''
   return (md, PortValue(md.IP['?push']))

if __name__ == '__main__':
   md = Toaster('ts', toasting_time = 60)
   engine = SimEngine(md, make_input_event)
   engine.runInteractiveMenu()
